#include <mainwindow.h>

mainWindow::mainWindow(QWidget *parent, Qt::WFlags f): QMainWindow(parent, f) {
	ui.setupUi(this);
	mocap = 0;
	mocap_x = 0;
	
	// yz
	connect(ui.selectFile, SIGNAL(clicked()), this, SLOT(selectFiles()));
	connect(ui.time, SIGNAL(valueChanged(int)), this, SLOT(mocapTime(int)));
	connect(ui.alpha, SIGNAL(valueChanged(int)), this, SLOT(mocapTime(int)));
	// x
	connect(ui.selectFile_x, SIGNAL(clicked()), this, SLOT(selectFiles_x()));
	connect(ui.time, SIGNAL(valueChanged(int)), this, SLOT(mocapTime_x(int)));
	connect(ui.alpha_x, SIGNAL(valueChanged(int)), this, SLOT(mocapTime_x(int)));
	
	//yz
	connect(ui.markerList, SIGNAL(itemSelectionChanged()), this, SLOT(mocapTime()));
	connect(ui.hueA, SIGNAL(valueChanged(int)), this, SLOT(showHSVColor(int)));
	connect(ui.hueB, SIGNAL(valueChanged(int)), this, SLOT(showHSVColor(int)));
	// x
	connect(ui.markerList_x, SIGNAL(itemSelectionChanged()), this, SLOT(mocapTime_x()));
	connect(ui.hueA_x, SIGNAL(valueChanged(int)), this, SLOT(showHSVColor_x(int)));
	connect(ui.hueB_x, SIGNAL(valueChanged(int)), this, SLOT(showHSVColor_x(int)));
	
	connect(ui.save, SIGNAL(clicked()), this, SLOT(saveMarkers()));
	
	ui.help->setUrl(QUrl("http://mocap-editow.w-i.pl/doc"));
}

/*
 * Wybor plikow animacji i rozpoczecie mocapu
 */
void mainWindow::selectFiles() {
	QFileDialog dialog(this);
	dialog.setFileMode(QFileDialog::ExistingFiles);
	dialog.setNameFilter(QString("Images (*.png *.jpg)"));
	dialog.setViewMode(QFileDialog::Detail);
	
	if (dialog.exec()) {
		fileList = dialog.selectedFiles();
	} else {
		return;
	}
	
	fileList.sort();
	ui.file->setText(fileList.join("; "));
	
	if (mocap != 0) {
		delete mocap;
	}
	
	// Utworz mocap
	mocap = new motionCap(fileList, QColor(255, 255, 0), this);

	// Ustaw parametry: kolor, rozmiar etc.
	if (ui.hueA->value() < ui.hueB->value()) {
		mocap->HMin = ui.hueA->value();
		mocap->HMax = ui.hueB->value();
	} else {
		mocap->HMin = ui.hueB->value();
		mocap->HMax = ui.hueA->value();
	}
	
	mocap->SV = 45;
	mocap->dotSize = 40;
	
	// Start :)
	mocap->findDots();
	
	// Usun z listy stare markery
	QList <QTreeWidgetItem *> items = ui.markerList->selectedItems();
	int count = items.size();
	for (int i = 0; i < count; i++) {
		ui.markerList->removeItemWidget(items[i], 0);
		ui.markerList->removeItemWidget(items[i], 1);
		delete items[i];
	}
	items.clear();
	
	// Dodaj do listy markerow
	for (int i = 0; i < mocap->dotList[0].size(); i++) {
		QStringList l(QString("Marker %1").arg(i+1));
		l.append(QString("%1").arg(i));
		items.append(new QTreeWidgetItem((QTreeWidgetItem *) 0,  l));
	}
	ui.markerList->insertTopLevelItems(0, items);
	
	// Pokaz markery w tabelce
	table();
	// Pokaz podglad
	mocapTime();
}

/*
 * Pokazuje sciezki wybranych markerow i punktu, w ktorych aktualnie sa
 */
void mainWindow::mocapTime(int v) {
	if (mocap == 0) {
		return;
	}
	
	int frame = (double)ui.time->value()/ui.time->maximum() * (fileList.size()-1);
	QString fileName = fileList[frame];
	
	QPixmap pix(fileName);
	QPainter paint(&pix);
	
	// Lista aktywnych sciezek
	QList <QTreeWidgetItem *> items = ui.markerList->selectedItems();
	QList <int> paths;
	
	// Zamien aktywne elementy ui.markerList na numery sciezek
	for (int dot = 0; dot < items.size(); dot++) {
		paths.append(items[dot]->text(1).toInt());
	}
	
	// Narysuj aktywne sciezki
	QPen pen(QColor(255, 0, 0, (double)ui.alpha->value()/100*255));
	pen.setWidthF(1.5);
	paint.setPen(pen);
	for (int fr = 1; fr < mocap->dotList.size(); fr++) {
		for (int i = 0; i < paths.size(); i++) {
			paint.drawLine(mocap->dotList[fr-1][paths[i]].x(), mocap->dotList[fr-1][paths[i]].y(), mocap->dotList[fr][paths[i]].x(), mocap->dotList[fr][paths[i]].y());
		}
	}
	
	// Narysuj kropki w miejscach gdzie jest srodek markera i hierarchie
	for (int i = 0; i < paths.size(); i++) {
		paint.setPen(QColor(255, 0, 0));
		//paint.drawLine(mocap->dotList[frame][paths[i]].x()-5, mocap->dotList[frame][paths[i]].y()-5, mocap->dotList[frame][paths[i]].x()+5, mocap->dotList[frame][paths[i]].y()+5);
		//paint.drawLine(mocap->dotList[frame][paths[i]].x()-5, mocap->dotList[frame][paths[i]].y()+5, mocap->dotList[frame][paths[i]].x()+5, mocap->dotList[frame][paths[i]].y()-5);
		paint.drawEllipse(mocap->dotList[frame][paths[i]].x()-2, mocap->dotList[frame][paths[i]].y()-2, 4, 4);
		
		// Narysuj hierarchie markerow (czyli wszystkie dzieci jego)
		for (int ch = 0; ch < items[i]->childCount(); ch++) {
			QPoint start(mocap->dotList[frame][ items[i]->text(1).toInt() ].x(), mocap->dotList[frame][ items[i]->text(1).toInt() ].y());
			int pathNum = items[i]->child(ch)->text(1).toInt();
			qDebug() << "Dziecko " << ch << ": " << pathNum;
			QPoint end(mocap->dotList[frame][pathNum].x(), mocap->dotList[frame][pathNum].y());
			
			paint.drawLine(start, end);
		}
	}
	
	ui.imageView->setPixmap(pix);
}

/*
 * Podglad koloru HSV dla osi Y,Z
 */
void mainWindow::showHSVColor(int i) {
	QPixmap pix(ui.hsvPreview->width(), ui.hsvPreview->height());
	QPainter paint(&pix);
	int h = ui.hsvPreview->height();
	int w = ui.hsvPreview->width();
	
	// Wybrany przedzial kolorow
	QColor c1, c2;
	c1.setHsv(ui.hueA->value(), 255, 255);
	c2.setHsv(ui.hueB->value(), 255, 255);
	
	paint.fillRect(0, 0, w, h/2, c1);
	paint.fillRect(0, h/2, w, h, c2);
	
	ui.hsvPreview->setPixmap(pix);
}


/*
 * Zapisanie wybranych markerow do pliku
 */
void mainWindow::saveMarkers() {
	// Sprawdzenie, czy sa zaznaczone markery na odpowiednich osiach
	if (ui.saveYZ->isChecked() && ui.markerList->selectedItems().size() == 0) {
		ui.saveYZWarn->setText("Wibierz markery do zapisania!");
		return;
	} else {
		ui.saveYZWarn->setText("");
	}
	
	if (ui.saveX->isChecked() && ui.markerList_x->selectedItems().size() == 0) {
		ui.saveXWarn->setText("Wibierz markery do zapisania!");
		return;
	} else {
		ui.saveXWarn->setText("");
	}
	
	// Dialog gdzie zapisac
	QString fileName = QFileDialog::getSaveFileName(this, tr("Zapisz pozycje markerow"), ".", tr("Mocap paths (*.mcp)"));
	if (fileName.size() == 0) {
		return;
	}
	
	QFile fp(fileName);
	fp.open(QIODevice::WriteOnly | QIODevice::Text);

	// Lista aktywnych sciezek
	QList <QTreeWidgetItem *> items = ui.markerList->selectedItems();
	QList <int> paths;
	QList <QTreeWidgetItem *> items_x = ui.markerList_x->selectedItems();
	QList <int> paths_x;
	
	// Zamien aktywne elementy ui.markerList na numery sciezek
	if (ui.saveYZ->isChecked()) {
		for (int dot = 0; dot < items.size(); dot++) {
			paths.append(items[dot]->text(1).toInt());
		}
	}
	if (ui.saveX->isChecked()) {
		for (int dot = 0; dot < items_x.size(); dot++) {
			paths_x.append(items_x[dot]->text(1).toInt());
		}
	}
	
	// Poczatek skryptu
	fp.write("import Blender\n"
		"from Blender import Ipo\n");
	
	for (int i = 0; i < paths.size(); i++) {
		// utworz wszystkie krzywe IPO
		fp.write( QString("ipo%1 = Blender.Ipo.New(\"Object\", \"Plane\")\n"
			"ipo%1.name = \"Marker_XYZ%1\"\n"
			"ipo%1.addCurve(\"LocY\")\n"
			"ipo%1.addCurve(\"LocZ\")\n"
			"ipo%1.addCurve(\"LocX\")\n"
			"ipoy%1 = ipo%1[Ipo.OB_LOCY]\n"
			"ipoz%1 = ipo%1[Ipo.OB_LOCZ]\n"
			"ipox%1 = ipo%1[Ipo.OB_LOCX]\n").arg(i).toAscii() );
	}
	/*for (int i = 0; i < paths_x.size(); i++) {
		// utworz wszystkie krzywe IPO
		fp.write( QString("ipo_x%1 = Blender.Ipo.New(\"Object\", \"Plane\")\n"
			"ipo_x%1.name = \"Marker_X%1\"\n"
			"ipo_x%1.addCurve(\"LocX\")\n"
			"ipox_x%1 = ipo_x%1[Ipo.OB_LOCX]\n").arg(i).toAscii() );
	}*/

	double ratio = ui.ratio->value();
	
	if (ui.saveX->isChecked() && ui.saveX->isChecked()) {
		// Zapis obu osi wg. tabelki
		fp.write( QString("# Zaisuje XYZ\n").toAscii() );
		// Zapis osi Y,Z
		for (int i = 0; i < items.size(); i++) {
			int pathNum = items[i]->text(1).toInt();
			for (int frame = 0; frame < mocap->dotList.size(); frame++) {
				// Dodaj wspolrzedne markerow
				fp.write( QString("ipoy%1.append((%2,%3))\n"
						"ipoz%1.append((%2,%4))\n").arg(i).arg(frame).arg(ratio * mocap->dotList[frame][pathNum].x()).arg(ratio * mocap->dotList[frame][pathNum].y()).toAscii() );
			}
		}
		
		// Zapis osi X
		// iteruj po zaznaczonych YZ'tach i sprawdz ktore X'y maja byc do nich przypisane
		for (int yz = 0; yz < items.size(); yz++) {
			int pathNum = items[yz]->text(1).toInt();
			int selected = -1;
			// Sprawdz, ktory marker YZ jest zaznaczony w tabelce
			for (int n = 0; n < mocap_x->dotList[0].size(); n++) {
				if (bt[pathNum][n]->isChecked()) {
					selected = n;
				}
			}
			if (selected != -1) {
				for (int frame = 0; frame < mocap_x->dotList.size(); frame++) {
					// Dodaj wspolrzedne markerow
					fp.write( QString("ipox%1.append((%2,%3))\n").arg(pathNum).arg(frame).arg(ratio * mocap_x->dotList[frame][selected].x()).toAscii() );
				}
			}
		}
	} else if (ui.saveYZ->isChecked()) {
		// Zapis osi Y,Z
		for (int i = 0; i < items.size(); i++) {
			int pathNum = items[i]->text(1).toInt();
			for (int frame = 0; frame < mocap->dotList.size(); frame++) {
				// Dodaj wspolrzedne markerow
				fp.write( QString("ipoy%1.append((%2,%3))\n"
						"ipoz%1.append((%2,%4))\n").arg(i).arg(frame).arg(ratio * mocap->dotList[frame][pathNum].x()).arg(ratio * mocap->dotList[frame][pathNum].y()).toAscii() );
			}
		}
	} else if (ui.saveX->isChecked()) {
		// Zapis osi X
		for (int i = 0; i < items_x.size(); i++) {
			int pathNum = items_x[i]->text(1).toInt();
			for (int frame = 0; frame < mocap_x->dotList.size(); frame++) {
				// Dodaj wspolrzedne markerow
				fp.write( QString("ipox%1.append((%2,%3))\n").arg(i).arg(frame).arg(ratio * mocap_x->dotList[frame][pathNum].x()).toAscii() );
			}
		}
	}
	
	fp.close();
}

void mainWindow::table() {
	if (mocap != 0 && mocap_x != 0) {
		QStringList labels;
		
		// Dodaj naglowki poziome (Y, Z)
		for (int i = 0; i < mocap->dotList[0].size(); i++) {
			labels.append(QString("Marker YZ %1").arg(i+1));
		}
		ui.table->setColumnCount(labels.size());
		ui.table->setHorizontalHeaderLabels(labels);
		labels.clear();
		
		// Dodaj naglowki pionowe (X)
		for (int i = 0; i < mocap_x->dotList[0].size(); i++) {
			labels.append(QString("Marker X %1").arg(i+1));
		}
		ui.table->setRowCount(labels.size());
		ui.table->setVerticalHeaderLabels(labels);
		
		// Utworz radioButtony, ich grupy i dodaj je do tablelki
		bt = new QRadioButton**[mocap->dotList[0].size()];
		bg = new QButtonGroup*[mocap->dotList[0].size()];
		
		for (int yz = 0; yz < mocap->dotList[0].size(); yz++) {
			bt[yz] = new QRadioButton*[mocap_x->dotList[0].size()];
			bg[yz] = new QButtonGroup(ui.table);
			for (int x = 0; x < mocap_x->dotList[0].size(); x++) {
				bt[yz][x] = new QRadioButton(ui.table);
				bg[yz]->addButton(bt[yz][x]);
				
				ui.table->setCellWidget(x, yz, bt[yz][x]);
			}
		}
	}
}
